package org.jsola.contract.service.impl;

import org.jsola.contract.common.ExampleKit;
import org.jsola.contract.constant.ContractConstants;
import org.jsola.contract.dao.ISealPositionDAO;
import org.jsola.contract.dto.SealPositionAddDTO;
import org.jsola.contract.dto.SealPositionUpdateDTO;
import org.jsola.contract.entity.SealPositionDO;
import org.jsola.contract.query.SealPositionQuery;
import org.jsola.contract.service.ISealPositionService;
import org.jsola.contract.vo.SealPositionListVO;
import org.jsola.contract.vo.SealPositionVO;
import org.jsola.core.Page;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 合同默认签章位置
 *
 * @author JanusMix
 */
@Service("contractSealPositionServiceImpl")
public class SealPositionServiceImpl implements ISealPositionService {

    @Autowired
    private ISealPositionDAO sealPositionDAO;

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public SealPositionVO save(SealPositionAddDTO sealPositionAddDTO, TokenUser tokenUser) {
        // 转DO
        SealPositionDO sealPositionDO = sealPositionAddDTO.to(SealPositionDO.class);
        if (sealPositionAddDTO.getTemplateId() != null) {
            //删除模板以前的位置
            List<SealPositionDO> positions = this.selectByTemplateIdAndAccountType(sealPositionDO.getTemplateId(),
                    sealPositionAddDTO.getAccountType(), tokenUser.getSiteId());
            this.deleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), positions.stream().map(SealPositionDO::getId).toArray());
        }
        // 保存
        sealPositionDO = save(sealPositionDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return sealPositionDO.to(SealPositionVO.class);
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public List<SealPositionVO> saveOrUpdate(List<SealPositionAddDTO> sealPositionAddDTOList, TokenUser tokenUser) {
        // 模板下原有印章位置全部删除
        List<Long> templateIds = sealPositionAddDTOList.parallelStream().map(SealPositionAddDTO::getTemplateId)
                .filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<SealPositionDO> sealPositionDOList = selectByTemplateIds(templateIds, tokenUser.getSiteId());
        deleteByIds(tokenUser.getSiteId(), tokenUser.getUserId()
                , sealPositionDOList.stream().map(SealPositionDO::getId).toArray());
        // 传入位置保存
        List<SealPositionVO> sealPositionVOList = new ArrayList<>();
        for (SealPositionAddDTO sealPositionAddDTO : sealPositionAddDTOList) {
            SealPositionDO sealPositionDO = sealPositionAddDTO.to(SealPositionDO.class);
            sealPositionDO = save(sealPositionDO, tokenUser.getSiteId(), tokenUser.getUserId());
            sealPositionVOList.add(sealPositionDO.to(SealPositionVO.class));
        }
        return sealPositionVOList;
    }

    @Override
    public List<SealPositionVO> saveOrUpdate(Long templateId, List<SealPositionAddDTO> sealPositionAddDTOList, TokenUser tokenUser) {
        // 模板下原有印章位置全部删除
        List<SealPositionDO> sealPositionDOList = selectByTemplateIds(Collections.singletonList(templateId), tokenUser.getSiteId());
        deleteByIds(tokenUser.getSiteId(), tokenUser.getUserId()
                , sealPositionDOList.stream().map(SealPositionDO::getId).toArray());
        // 传入位置保存
        List<SealPositionVO> sealPositionVOList = new ArrayList<>();
        for (SealPositionAddDTO sealPositionAddDTO : sealPositionAddDTOList) {
            SealPositionDO sealPositionDO = sealPositionAddDTO.to(SealPositionDO.class);
            sealPositionDO.setTemplateId(templateId);
            sealPositionDO = save(sealPositionDO, tokenUser.getSiteId(), tokenUser.getUserId());
            sealPositionVOList.add(sealPositionDO.to(SealPositionVO.class));
        }
        return sealPositionVOList;
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public List<SealPositionVO> batchSave(List<SealPositionAddDTO> sealPositionAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(sealPositionAddDTOList)) {
            return null;
        }
        List<SealPositionDO> sealPositionDOList = sealPositionAddDTOList
                .parallelStream()
                .map(sealPositionAddDTO -> {
                    SealPositionDO sealPositionDO = sealPositionAddDTO.to(SealPositionDO.class);
                    sealPositionDO.preInsert(tokenUser.getUserId());
                    sealPositionDO.setSiteId(tokenUser.getSiteId());
                    return sealPositionDO;
                }).collect(Collectors.toList());
        sealPositionDAO.insertListAndSetId(sealPositionDOList);
        return sealPositionDOList
                .parallelStream()
                .map(sealPositionDO -> sealPositionDO.to(SealPositionVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public int update(SealPositionUpdateDTO sealPositionUpdateDTO, TokenUser tokenUser) {
        //转DO
        SealPositionDO sealPositionDO = sealPositionUpdateDTO.to(SealPositionDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(sealPositionDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, Long... sealPositionIds) {
        return deleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) sealPositionIds);
    }


    @Override
    public SealPositionVO selectById(Long sealPositionId, String siteId) {
        SealPositionDO sealPositionDO = selectDOById(sealPositionId, siteId);
        if (sealPositionDO == null) {
            return null;
        }
        return sealPositionDO.to(SealPositionVO.class);
    }

    @Override
    public List<SealPositionListVO> select(SealPositionQuery sealPositionQuery, String siteId) {
        List<SealPositionDO> sealPositionDOList = selectDO(sealPositionQuery, siteId);
        if (CollectionUtils.isEmpty(sealPositionDOList)) {
            return sealPositionDOList == null ? null : new ArrayList<>();
        }
        return sealPositionDOList.stream()
                .map(sealPositionDO -> sealPositionDO.to(SealPositionListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(SealPositionQuery sealPositionQuery, String siteId) {
        Example example = buildExample(sealPositionQuery, siteId);
        return sealPositionDAO.selectCountByExample(example);
    }

    @Override
    public Page<SealPositionListVO> selectPage(SealPositionQuery sealPositionQuery, String siteId) {
        Example example = buildExample(sealPositionQuery, siteId);
        Page<SealPositionDO> page = sealPositionDAO.selectPageByExample(example,
                sealPositionQuery.getPageNo(),
                sealPositionQuery.getPageSize());

        return page.to(SealPositionListVO.class);
    }

    @Override
    public SealPositionDO selectDOById(Long sealPositionId, String siteId) {
        return listById(sealPositionId, siteId);
    }

    @Override
    public List<SealPositionDO> selectDO(SealPositionQuery sealPositionQuery, String siteId) {
        Example example = buildExample(sealPositionQuery, siteId);
        return sealPositionDAO.selectByExample(example);
    }

    @Override
    public List<SealPositionDO> selectByTemplateId(Long templateId, String siteId) {
        Example example = new Example(SealPositionDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andEqualTo("templateId", templateId);
        return sealPositionDAO.selectByExample(example);
    }

    @Override
    public List<SealPositionDO> selectByTemplateIds(List<Long> templateIds, String siteId) {
        if (CollectionUtils.isEmpty(templateIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(SealPositionDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andIn("templateId", templateIds);
        return sealPositionDAO.selectByExample(example);
    }

    @Override
    public List<SealPositionDO> selectByTemplateIdAndAccountType(Long templateId, Integer accountType, String siteId) {
        Example example = new Example(SealPositionDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andEqualTo("templateId", templateId)
                .andEqualTo("accountType", accountType);
        return sealPositionDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public void updateMaxSealPage(Long templateId, Integer totalPage, TokenUser tokenUser) {
        // 更新模板签章页码大于pdf总页码的
        Example example = new Example(SealPositionDO.class);
        example.and()
                .andEqualTo("templateId", templateId)
                .andGreaterThan("sealPage", totalPage)
                .andEqualTo("siteId", tokenUser.getSiteId());

        SealPositionDO sealPositionDO = new SealPositionDO();
        sealPositionDO.setSealPage(totalPage);

        sealPositionDAO.updateByExampleSelective(sealPositionDO, example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param sealPositionQuery 查询参数
     * @param siteId            所属站点id
     * @return example
     */
    private Example buildExample(SealPositionQuery sealPositionQuery, String siteId) {
        Example example = new Example(SealPositionDO.class);
        example.and()
                .andEqualTo("siteId", siteId);
        if (sealPositionQuery.getTemplateId() != null) {
            example.and().andEqualTo("templateId", sealPositionQuery.getTemplateId());
        }
        if (sealPositionQuery.getAppendixId() != null) {
            example.and().andEqualTo("appendixId", sealPositionQuery.getAppendixId());
        }
        if (sealPositionQuery.getAccountType() != null) {
            example.and().andEqualTo("accountType", sealPositionQuery.getAccountType());
        }
        if (sealPositionQuery.getType() != null) {
            example.and().andEqualTo("type", sealPositionQuery.getType());
        }
        if (sealPositionQuery.getSealPage() != null) {
            example.and().andEqualTo("sealPage", sealPositionQuery.getSealPage());
        }
        if (sealPositionQuery.getSealPositionX() != null) {
            example.and().andEqualTo("sealPositionX", sealPositionQuery.getSealPositionX());
        }
        if (sealPositionQuery.getSealPositionY() != null) {
            example.and().andEqualTo("sealPositionY", sealPositionQuery.getSealPositionY());
        }
        // 排序
        ExampleKit.setExampleOrder(example, sealPositionQuery.getOrders());
        return example;
    }
}




